﻿using System;
using TouchSocket.Core.Config;
using TouchSocket.Rpc.TouchRpc;
using TouchSocket.Sockets;
using TouchSocket.Rpc;
using TouchSocket.Http;
using TouchSocket.Core.Log;
using TouchSocket.Rpc.TouchRpc.Plugins;


namespace Updater.Core
{
    public class UPTcpService:IDisposable
    {
        /// <summary>
        /// 想要实现业务处理 请实现IserverEvent接口并赋值
        /// </summary>
        public IServerEvent ServerEvent { get; set; }
        /// <summary>
        /// 服务器组件
        /// </summary>
        private TcpTouchRpcService service;
        /// <summary>
        /// 服务器组件
        /// </summary>
        public TcpTouchRpcService Service { get { return service; } }
        /// <summary>
        /// RPC服务
        /// </summary>
        private RpcStore rpcStore;
        /// <summary>
        /// RPC服务，想要实现RPC调用请继承RpcServer类并且注册RpcStore.RegisterServer<MyRpcServer>();
        /// </summary>
        public RpcStore RpcStore { get { return rpcStore; } }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="host">服务器通讯端口</param>
        public UPTcpService(int host)
        {
            service=new TcpTouchRpcService();
            //生成给touch配置
            TouchSocketConfig config = new TouchSocketConfig();
            //设置服务器端口
            config.SetListenIPHosts(new IPHost[] { new IPHost(host) });
            //设置最大连接数
            config.SetMaxCount(10000);
            //设置最大线程数
            config.SetThreadCount(100);
            //设置token
            config.SetVerifyToken("TouchRpc");
            config.SetResponseType(ResponseType.Both);
            
            //配置服务器
            service.Setup(config);
            //启动服务器
            service.Start();
            
            rpcStore = new RpcStore(new TouchSocket.Core.Dependency.Container());
            rpcStore.AddRpcParser("tcpTouchRpcParser", service);
            Init_Event(new DefaultServerEvent());
            
        }
        public void Message(string str)
        {
            service.Logger.Message(str);
        }
        /// <summary>
        /// 初始化业务处理
        /// </summary>
        public void Init_Event(IServerEvent serverEvent)
        {
            this.ServerEvent= serverEvent;
            service.Connected += ServerEvent.Connected;
            service.Connecting += ServerEvent.Connecting;
            service.Disconnected += ServerEvent.Disconnected;
            service.FileTransfered += ServerEvent.FileTransfered;
            service.FileTransfering += ServerEvent.FileTransfering;
            service.Handshaked += ServerEvent.Handshaked;
            service.Handshaking += ServerEvent.Handshaking;
            service.IDChanged += ServerEvent.IDChanged;
            service.Received += ServerEvent.Received;
            service.StreamTransfered += ServerEvent.StreamTransfered;
            service.StreamTransfering += ServerEvent.StreamTransfering;
        }
        /// <summary>
        /// 分享RPC服务,用于开发中来获取RPC调用类；
        /// </summary>
        /// <param name="host"></param>
        /// <returns></returns>
        public string ShareProxy(int host)
        {
            rpcStore.ProxyUrl = "/proxy";//代理url
            rpcStore.OnRequestProxy = (request) =>//此处做请求验证，保证代理文件安全。
            {
                if (request.TryGetQuery("token", out string value) && value == "123")
                {
                    return true;
                }
                return false;
            };
            rpcStore.ShareProxy(new IPHost(host));

            return "http://127.0.0.1:"+host.ToString()+"/proxy?proxy=all&token=123";
        }

        public void Dispose()
        {
            service.Stop();
            
            this.RpcStore.SafeDispose();
            this.service.SafeDispose();
        }
    }
  

    public class MyTouchRpcAttribute : TouchRpcAttribute
    {
        private readonly string m_route;

        public MyTouchRpcAttribute(string route = default)
        {
            this.m_route = route;
        }

        public override string GetInvokenKey(MethodInstance methodInstance)
        {
            if (m_route.IsNullOrEmpty())
            {
                return base.GetInvokenKey(methodInstance);
            }
            return m_route;
        }
    }

    public class MyRpcActionFilterAttribute : Attribute, IRpcActionFilter
    {
        /// <summary>
        /// 在执行RPC之前。
        /// <para>当<paramref name="invokeResult"/>的InvokeStatus不为<see cref="InvokeStatus.Ready"/>。则不会执行RPC</para>
        /// <para>同时，当<paramref name="invokeResult"/>的InvokeStatus为<see cref="InvokeStatus.Success"/>。会直接返回结果</para>
        /// </summary>
        /// <param name="caller"></param>
        /// <param name="invokeResult"></param>
        /// <param name="methodInstance"></param>
        /// <param name="ps"></param>
        public void Executing(object caller, ref InvokeResult invokeResult, MethodInstance methodInstance, object[] ps)
        {
            if (caller is TcpTouchRpcSocketClient client)
            {
                client.Logger.Message($"即将执行RPC-{methodInstance.Name}");
            }
        }

        /// <summary>
        /// 成功执行后。
        /// <para>如果修改<paramref name="invokeResult"/>的InvokeStatus，或Result。则会影响RPC最终结果</para>
        /// </summary>
        /// <param name="caller"></param>
        /// <param name="invokeResult"></param>
        /// <param name="methodInstance"></param>
        public void Executed(object caller, ref InvokeResult invokeResult, MethodInstance methodInstance)
        {
            if (caller is TcpTouchRpcSocketClient client)
            {
                client.Logger.Message($"执行RPC-{methodInstance.Name}完成，状态={invokeResult.Status}");
            }
        }

        /// <summary>
        /// 执行遇见异常。
        /// <para>如果修改<paramref name="invokeResult"/>的InvokeStatus，或Result。则会影响RPC最终结果</para>
        /// </summary>
        /// <param name="caller"></param>
        /// <param name="invokeResult"></param>
        /// <param name="methodInstance"></param>
        /// <param name="exception"></param>
        public void ExecutException(object caller, ref InvokeResult invokeResult, MethodInstance methodInstance, Exception exception)
        {
            if (caller is TcpTouchRpcSocketClient client)
            {
                client.Logger.Message($"执行RPC-{methodInstance.Name}异常，信息={invokeResult.Message}");
            }
        }
    }

    internal class MyTouchRpcPlugin : TouchRpcPluginBase
    {
        public override void OnHandshaking(ITouchRpc client, VerifyOptionEventArgs e)
        {
            if (e.Token == "123")
            {
                e.IsPermitOperation = true;
                e.Handled = true;
                return;
            }
            base.OnHandshaking(client, e);
        }
    }
}
